//! \file GUI.cpp
//! \brief TODO: Document
// -----------------------------------------------------------------------------
//! This program is free software; you can redistribute it and/or
//! modify it under the terms of the GNU General Public License
//! as published by the Free Software Foundation; either version 2
//! of the License, or (at your option) any later version.
//!
//! This program is distributed in the hope that it will be useful,
//! but WITHOUT ANY WARRANTY; without even the implied warranty of
//! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//! GNU General Public License for more details.
//!
//! You should have received a copy of the GNU General Public License
//! along with this program; if not, write to the Free Software Foundation,
//! Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// -----------------------------------------------------------------------------

#include "Gui.h"

#include "Core.h"

#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <CEGUI.h>
#include <CEGUI/RendererModules/OpenGL/CEGUIOpenGLRenderer.h>
//#include <CEGUIDefaultResourceProvider.h>
//using namespace CEGUI;

namespace Gui {

// =====[ Local Definitions ]===================================================

// =====[ Local DataTypes ]=====================================================

// =====[ Local Variables ]=====================================================



  // SDL
static SDL_Surface *pSurface = NULL;

  // CEGUI
static CEGUI::WindowManager *pWm = NULL;
// static CEGUI::System *d_system;       // the gui system
static CEGUI::Window *pRoot = NULL;
static CEGUI::Font *pFont = NULL;


bool must_quit = false;
double last_time_pulse = 0.001*static_cast<double>(SDL_GetTicks());


// =====[ Local Functions ]=====================================================

static void *_Gui_Run(void *Arg);
static tERROR _Gui_Shutdown(tERROR Error);


static tERROR _Gui_Init(void);
static tERROR _Gui_InitSDL(void);
static tERROR _Gui_InitOpenGL(void);
static tERROR _Gui_InitCEGUI(void);
static tERROR CreateCEGUIResourceProvider(void);
static tERROR CreateCEGUIRoot(void);

static tERROR NewWindowConsole(CEGUI::Window *pParent);
static tERROR NewWindowAbout(CEGUI::Window *pParent);

static tERROR NewMenuMain(CEGUI::Window *pParent);

static tERROR NewMenuItemFile(CEGUI::Window *pParent);
static tERROR NewMenuItemHelp(CEGUI::Window *pParent);

static bool fileAbout(const CEGUI::EventArgs&);
static bool fileQuit(const CEGUI::EventArgs&);




void inject_input(bool& must_quit);
void inject_time_pulse(double& last_time_pulse);
void render_gui();
void handle_mouse_down(Uint8 button);
void handle_mouse_up(Uint8 button);

// =====[ Private (Internal) Methods ]==========================================

// =====[ Local Implementation ]================================================


// =====[ Public Methods ]======================================================


// TODO: comment
static const Core::tTask Task
{
  &_Gui_Run,                  // Run
  &_Gui_Shutdown              // Shutdown
};

// =============================================================================
// Implement: X
// -----------------------------------------------------------------------------
tERROR Start(void)
{
  tERROR Error;

  // Initialize the GUI.
  _Gui_Init();

//  Error = _Gui_InitSDL(); // TODO: check for errors
//  Error = _Gui_InitOpenGL(); // TODO: check for errors
//  Error = _Gui_InitCEGUI(); // TODO: check for errors.



  Error = NewMenuMain(NULL);
  Error = NewWindowConsole(NULL);

  Core::TaskNew(&Task);


  // TODO: fork the thread


  // TODO: create a thread and return?

//  using namespace CEGUI;

  // -------------------- CREATE THE ROOT "WINDOW"
//  using namespace CEGUI;



  // Finally, return success.
  return (std::ERR_NONE);
}


// =============================================================================
// Implement: X
// -----------------------------------------------------------------------------
tERROR Stop(tERROR Error)
{
  must_quit = true;

  // TODO: implement function
  return (Error);
}



//void render_gui()
//{
//  /* clear the colour buffer */
//  glClear( GL_COLOR_BUFFER_BIT );
//
//  GUI::DisplayTask(NULL);
//
//  /* render the GUI :) */
//  CEGUI::System::getSingleton().renderGUI();
//
//  /* Update the screen */
//  SDL_GL_SwapBuffers();
//}


// =====[ Private Methods ]=====================================================


static void *_Gui_Run(void *Arg)
{
  while (!must_quit)
  {
    inject_input(must_quit);
    inject_time_pulse(last_time_pulse);
    render_gui();
  }

  return (NULL);
}


static tERROR _Gui_Shutdown(tERROR Error)
{
  must_quit = true;
  return (ERR_NONE);
}


// =============================================================================
// FxName
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR _Gui_Init(void)
{
  tERROR Error;

  if (Error = _Gui_InitSDL() != ERR_NONE)     { return (Error); }
  if (Error = _Gui_InitOpenGL() != ERR_NONE)  { return (Error); }
  if (Error = _Gui_InitCEGUI() != ERR_NONE)   { return (Error); }
}


// =============================================================================
// _Gui_InitSDL
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR _Gui_InitSDL(void)
{
  // Initialize SDL.
  if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
    { return (Stop(ERR_GUI_DISPLAY_START)); }

  // Create our SDL drawing surface.
  pSurface = SDL_SetVideoMode(800, 600, 0, SDL_OPENGL);
  if (pSurface == NULL)
    { return (Stop(ERR_SDL_SURFACE_CREATION)); }

  // Configure SDL to play nice with our OpenGL host.
  SDL_ShowCursor(SDL_DISABLE);                  // Hide the SDL cursor.
  SDL_EnableUNICODE(1);                         // Activate unicode translation for SDL key events.
  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);  // Enable the key repeats for CEGUI.

  // Finally, return success.
  return (ERR_NONE);
}


// =============================================================================
// _Gui_InitOpenGL
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR _Gui_InitOpenGL(void)
{
  // Configure OpenGL to host our SDL surface and CEGUI.
  glEnable(GL_CULL_FACE);                       // Enable the culling of polygons based on their winding in window coordinates.
  glDisable(GL_FOG);                            // Disable the blending of a fog color into the post-texturing color.
  glClearColor(0.0f,0.0f,0.0f,1.0f);            // Specify clear values for the color buffers.
  glViewport(0,0, 800,600);                     // Set the OpenGL view port.

  glMatrixMode(GL_PROJECTION);                  // TODO: comment
  glLoadIdentity();                             // TODO: comment
  gluPerspective(45.0, 800.0/600.0, 0.1,100.0); // TODO: comment
  glMatrixMode(GL_MODELVIEW);                   // TODO: comment
  glLoadIdentity();                             // TODO: comment

  // Finally, return success.
  return (ERR_NONE);
}


// =============================================================================
// _Gui_InitCEGUI
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR _Gui_InitCEGUI(void)
{
  // Connect CEGUI up with the OpenGL renderer.
  CEGUI::OpenGLRenderer::bootstrapSystem();

  // Initialize the resource provider.
  CreateCEGUIResourceProvider(); // TODO: error check

  // Create (load) the TaharezLook scheme file (this auto-loads the
  // TaharezLook looknfeel and imageset files).
  CEGUI::SchemeManager::getSingleton().create("TaharezLook.scheme");

  // Create (load) a font.  The first font loaded automatically becomes the
  // default font, but note that the scheme might have already loaded a font,
  // so there may already be a default set - if we want the "Commonweath-10"
  // font to definitely be the default, we should set the default explicitly
  // afterwards.
  pFont = &(CEGUI::FontManager::getSingleton().create("DejaVuSans-10.font"));

/*
  //System::getSingleton().setDefaultFont( "DejaVuSans-10" ); TODO: something??
  // Load the default font. TODO: load during the init stuff...
  pFont = &FontManager::getSingleton().create("DejaVuSans-10.font");
  */


  CEGUI::System::getSingleton().setDefaultMouseCursor("TaharezLook", "MouseArrow");
  //System::getSingleton().setDefaultToolTip( "TaharezLook/Tooltip" );

  // TODO: comment
  CreateCEGUIRoot();

  // Finally, return success.
  return (ERR_NONE);
}


// =============================================================================
// CreateCEGUIResourceProvider
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR CreateCEGUIResourceProvider(void)
{
  // Initialize the required directories for the DefaultResourceProvider.
  CEGUI::DefaultResourceProvider *pRp =
      static_cast<CEGUI::DefaultResourceProvider*> (CEGUI::System::getSingleton().getResourceProvider());

  // Set the resource group directory paths.
  pRp->setResourceGroupDirectory("schemes", "./datafiles/schemes/");
  pRp->setResourceGroupDirectory("imagesets", "./datafiles/imagesets/");
  pRp->setResourceGroupDirectory("fonts", "./datafiles/fonts/");
  pRp->setResourceGroupDirectory("layouts", "./datafiles/layouts/");
  pRp->setResourceGroupDirectory("looknfeels", "./datafiles/looknfeel/");
  pRp->setResourceGroupDirectory("lua_scripts", "./datafiles/lua_scripts/");

  // This is only needed when using Xerces and to specify the schemas location.
  pRp->setResourceGroupDirectory("schemas", "./datafiles/xml_schemas/");

  // Set the default resource groups to be used.
  CEGUI::Imageset::setDefaultResourceGroup("imagesets");
  CEGUI::Font::setDefaultResourceGroup("fonts");
  CEGUI::Scheme::setDefaultResourceGroup("schemes");
  CEGUI::WidgetLookManager::setDefaultResourceGroup("looknfeels");
  CEGUI::WindowManager::setDefaultResourceGroup("layouts");
  CEGUI::ScriptModule::setDefaultResourceGroup("lua_scripts");

  // Setup default group for validation schemas.
  CEGUI::XMLParser* pParser = CEGUI::System::getSingleton().getXMLParser();
  if (pParser->isPropertyPresent("SchemaDefaultResourceGroup"))
    { pParser->setProperty("SchemaDefaultResourceGroup", "schemas"); }

  // Finally, return success.
  return (ERR_NONE);
}


// =============================================================================
// CreateCEGUIRoot
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR CreateCEGUIRoot(void)
{
  using namespace CEGUI;

  // Grab a reference to the window manager.
  pWm = WindowManager::getSingletonPtr();
  if (pWm == NULL) { /* TODO: fault and shutdown */ }

  // Create the root window.
  pRoot = pWm->createWindow("DefaultWindow", "root");
  if (pRoot == NULL) { /* TODO: fault and shutdown */ }

  // Set the active GUI sheet (root) window.
  System::getSingleton().setGUISheet(pRoot);

  // Return success.
  return (ERR_NONE);
}


// =============================================================================
// NewWindowConsole
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR NewWindowConsole(CEGUI::Window *pParent)
{
  using namespace CEGUI;
  Window *pWindow;
  UDim MenuBarBottom(0, pFont->getLineSpacing(12));

  // If no parent was provided, we will attach it to the root.
  if (pParent == NULL) { pParent = pRoot; }

  // Create the window.
  pWindow = pWm->createWindow("TaharezLook/FrameWindow");
  if (pWindow == NULL) { /* TODO: error */ }

  // Configure the menu bar as needed.
  pWindow->setText("Console");
  pWindow->setAlwaysOnTop(true);      // Keep it on top.
//  pWindow->setModalState(true);
//  pWindow->setAlpha(0.5f);

  pWindow->setArea(UDim(0,0), UDim(0.80f,0), UDim(1,0), UDim(0.20f,0)); // Set the size.

//  void setArea(const UDim& xpos, const UDim& ypos, const UDim& width, const UDim& height);
//  UDim(float scale, float offset) : d_scale(scale), d_offset(offset) {}

  // TODO: clean below the line ----------------------------

//  // position a quarter of the way in from the top-left of parent.
//  pWindow->setPosition( UVector2( UDim( 0.25f, 0 ), UDim( 0.25f, 0 ) ) );
//
//  // set size to be half the size of the parent
//  pWindow->setSize( UVector2( UDim( 0.5f, 0 ), UDim( 0.5f, 0 ) ) );


  pParent->addChildWindow(pWindow);   // Attach it to the parent.

  // Finally, return no error.
  return (ERR_NONE);
}


// =============================================================================
// NewWindowAbout
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR NewWindowAbout(CEGUI::Window *pParent)
{
  using namespace CEGUI;
  Window *pWindow;

  // If no parent was provided, we will attach it to the root.
  if (pParent == NULL) { pParent = pRoot; }

  // Create the window.
  pWindow = pWm->createWindow("TaharezLook/FrameWindow");
  if (pWindow == NULL) { /* TODO: error */ }

  // Configure the menu bar as needed.
  pWindow->setText("About");
  pWindow->setAlwaysOnTop(true);      // Keep it on top.
  pWindow->setModalState(true);
  pWindow->setAlpha(0.5f);

  // TODO: clean below the line ----------------------------

  // position a quarter of the way in from the top-left of parent.
  pWindow->setPosition( UVector2( UDim( 0.25f, 0 ), UDim( 0.25f, 0 ) ) );

  // set size to be half the size of the parent
  pWindow->setSize( UVector2( UDim( 0.5f, 0 ), UDim( 0.5f, 0 ) ) );


  pParent->addChildWindow(pWindow);   // Attach it to the parent.

  // Finally, return no error.
  return (ERR_NONE);






//  Window* myRoot =  wmgr.getWindow("root");
//
//  FrameWindow* fWnd = static_cast<FrameWindow*>(
//  wmgr.createWindow( "TaharezLook/FrameWindow", "testWindow" ));
//
//  myRoot->addChildWindow( fWnd );
//
//  // position a quarter of the way in from the top-left of parent.
//  fWnd->setPosition( UVector2( UDim( 0.25f, 0 ), UDim( 0.25f, 0 ) ) );
//
//  // set size to be half the size of the parent
//  fWnd->setSize( UVector2( UDim( 0.5f, 0 ), UDim( 0.5f, 0 ) ) );
//
//  fWnd->setText( "Hello World!" );
}


// =============================================================================
// NewMenuMain
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR NewMenuMain(CEGUI::Window *pParent)
{
  using namespace CEGUI;
  Window *pMenuBar;
//  Window *pMenuItem;
//  Window *pItem;
//  Window *pPopup;
  UDim MenuBarBottom(0, pFont->getLineSpacing(2));

  // If no parent was provided, we will attach it to the root.
  if (pParent == NULL) { pParent = pRoot; }

  // Create the menu bar.
  pMenuBar = pWm->createWindow("TaharezLook/Menubar");             // Create the menu.
  if (pMenuBar == NULL) { /* TODO: error */ }

  // Configure the menu bar as needed.
  pMenuBar->setArea(UDim(0,0), UDim(0,0), UDim(1,0), MenuBarBottom); // Set the size.
  pMenuBar->setAlwaysOnTop(true);                                    // Keep it on top.
  pParent->addChildWindow(pMenuBar);                                 // Attach it to the parent.

  // Add the menu items to the menu bar.
  NewMenuItemFile(pMenuBar); // [File]
  NewMenuItemHelp(pMenuBar); // [Help]

//  // Add the [File] menu item.
//  Window* file = pWm->createWindow("TaharezLook/MenuItem");
//  file->setText("File");
//  pMenuBar->addChildWindow(file);
//
//  // file popup
//  Window* popup = pWm->createWindow("TaharezLook/PopupMenu");
//  file->addChildWindow(popup);
//
//  // quit item in file menu
//  Window* item = pWm->createWindow("TaharezLook/MenuItem");
//  item->setText("Quit");
//  //item->subscribeEvent("Clicked", Event::Subscriber(&ScrollablePaneSample::fileQuit, this));
//  item->subscribeEvent("Clicked", Event::Subscriber(&GUI::fileQuit));
//  popup->addChildWindow(item);

/*
  // demo menu item
  Window* demo = pWm->createWindow("TaharezLook/MenuItem");
  demo->setText("Demo");
  pMenuBar->addChildWindow(demo);

  // demo popup
  popup = pWm->createWindow("TaharezLook/PopupMenu");
  demo->addChildWindow(popup);

  // demo -> new window
  item = pWm->createWindow("TaharezLook/MenuItem");
  item->setText("New dialog");
  item->setTooltipText("Hotkey: Space");
//  item->subscribeEvent("Clicked", Event::Subscriber(&ScrollablePaneSample::demoNewDialog, this));
  popup->addChildWindow(item);
*/


//  // TODO: error checking?

//  using namespace CEGUI;
//  WindowManager& wmgr = WindowManager::getSingleton();
//
//  // If no parent was provided, we will attach it to the root.
//  if (pWindow == NULL) { pWindow = wmgr.getWindow("root"); }
//
//
//  FrameWindow* fWnd = static_cast<FrameWindow*>(
//  wmgr.createWindow( "TaharezLook/FrameWindow", "Main" ));
//
//  pWindow->addChildWindow( fWnd );
//
//  // position a quarter of the way in from the top-left of parent.
//  fWnd->setPosition( UVector2( UDim( 0.25f, 0 ), UDim( 0.25f, 0 ) ) );
//
//  // set size to be half the size of the parent
//  fWnd->setSize( UVector2( UDim( 0.5f, 0 ), UDim( 0.5f, 0 ) ) );
//
//  fWnd->setText( "Hello World!" );

  // Finally, return no error.
  return (ERR_NONE);
}


// =============================================================================
// NewMenuFile
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR NewMenuItemFile(CEGUI::Window *pParent)
{
  using namespace CEGUI;
  Window *pMenu, *pPopup, *pItem;

  // Validate our arguments.
  if (pParent == NULL) { /* TODO: error */ }

  // Create the menu item.
  pMenu = pWm->createWindow("TaharezLook/MenuItem");
  pMenu->setText("File");         // Set the displayed text.
  pParent->addChildWindow(pMenu); // Attach to the parent.

  // Create the menu popup.
  pPopup = pWm->createWindow("TaharezLook/PopupMenu");
  pMenu->addChildWindow(pPopup);  // Attach the popup to the menu.

  // "Quit" item in the menu.
  pItem = pWm->createWindow("TaharezLook/MenuItem");
  pItem->setText("Quit");         // Set the displayed text.
  //item->subscribeEvent("Clicked", Event::Subscriber(&ScrollablePaneSample::fileQuit, this));
  pItem->subscribeEvent("Clicked", Event::Subscriber(&fileQuit));
  pPopup->addChildWindow(pItem);  // Attach the item to the popup.

  // Finally, return no error.
  return (ERR_NONE);
}


// =============================================================================
// NewMenuHelp
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
//!
//! \b Example: \code
//! FxName(0);
//! \endcode
// -----------------------------------------------------------------------------
static tERROR NewMenuItemHelp(CEGUI::Window *pParent)
{
  using namespace CEGUI;
  Window *pMenu, *pPopup, *pItem;

  // Validate our arguments.
  if (pParent == NULL) { /* TODO: error */ }

  // Create the menu item.
  pMenu = pWm->createWindow("TaharezLook/MenuItem");
  pMenu->setText("Help");         // Set the displayed text.
  pParent->addChildWindow(pMenu); // Attach to the parent.

  // Create the menu popup.
  pPopup = pWm->createWindow("TaharezLook/PopupMenu");
  pMenu->addChildWindow(pPopup);  // Attach the popup to the menu.

  // "About" item in the menu.
  pItem = pWm->createWindow("TaharezLook/MenuItem");
  pItem->setText("About");         // Set the displayed text.
  pItem->subscribeEvent("Clicked", Event::Subscriber(&fileAbout));
  pPopup->addChildWindow(pItem);  // Attach the item to the popup.

  // Finally, return no error.
  return (ERR_NONE);
}




// quit menu item handler
static bool fileAbout(const CEGUI::EventArgs&)
{
//    d_sampleApp->setQuitting(true);
  NewWindowAbout(pRoot);

  puts("About");
    return true;
}

// quit menu item handler
static bool fileQuit(const CEGUI::EventArgs&)
{
//    d_sampleApp->setQuitting(true);
  puts("Quit");
    return true;
}













// =============================================================================
// _UI_DisplayTask
// -----------------------------------------------------------------------------
//! TODO: document
//!
//! \param [in] Arg
//!   TODO: document
//!
//! \retval Exception
//!   The success status of the requested operation.
//!   - eOKAY: Execution occurred as requested.
//!   .
// -----------------------------------------------------------------------------
int DisplayTask(void* Data)
{
  static SDL_Rect Loc;
  static SDL_Surface* pImage = NULL;


  if (pImage == NULL)
  {
    // Create our image.
    pImage = SDL_LoadBMP("hello.bmp");
    // Initialize the location.
    Loc.x = 0;
    Loc.y = 0;
    Loc.w = 100;
    Loc.h = 63;
  }

  if (pImage == NULL) return -1;


//  while (IsRunning == eTRUE)
//  while (1)
  {
    // ROSO: something.
    SDL_BlitSurface(pImage, NULL, pSurface, &Loc);

    // Update Screen
//    SDL_Flip(pSurface);

    // Pause
//    SDL_Delay(100);

    // Advance the location.
    if (++(Loc.x) > 640) Loc.x = 0;
    if (++(Loc.y) > 480) Loc.y = 0;
  }

  // Finally, return success.
  //return (ERR_NONE);
  return 0;
}

















void inject_input(bool& must_quit)
{
  SDL_Event e;

  // go through all available events
  while (SDL_PollEvent(&e))
  {
    // we use a switch to determine the event type
    switch (e.type)
    {
      // mouse motion handler
      case SDL_MOUSEMOTION:
        // we inject the mouse position directly.
        CEGUI::System::getSingleton().injectMousePosition(
          static_cast<float>(e.motion.x),
          static_cast<float>(e.motion.y)
        );
        break;

      // mouse down handler
      case SDL_MOUSEBUTTONDOWN:
        // let a special function handle the mouse button down event
        handle_mouse_down(e.button.button);
        break;

      // mouse up handler
      case SDL_MOUSEBUTTONUP:
        // let a special function handle the mouse button up event
        handle_mouse_up(e.button.button);
        break;


      // key down
      case SDL_KEYDOWN:
        // to tell CEGUI that a key was pressed, we inject the scan code.
        CEGUI::System::getSingleton().injectKeyDown(e.key.keysym.scancode);

        // as for the character it's a little more complicated. we'll use for translated unicode value.
        // this is described in more detail below.
        if (e.key.keysym.unicode != 0)
        {
          CEGUI::System::getSingleton().injectChar(e.key.keysym.unicode);
        }
        break;

      // key up
      case SDL_KEYUP:
        // like before we inject the scan code directly.
        CEGUI::System::getSingleton().injectKeyUp(e.key.keysym.scancode);
        break;


      // WM quit event occurred
      case SDL_QUIT:
        must_quit = true;
        break;

    }

  }

}


void inject_time_pulse(double& last_time_pulse)
{
  // get current "run-time" in seconds
  double t = 0.001*SDL_GetTicks();

  // inject the time that passed since the last call
  CEGUI::System::getSingleton().injectTimePulse( float(t-last_time_pulse) );

  // store the new time as the last time
  last_time_pulse = t;
}


void render_gui()
{
  // Clear the OpenGL color buffer.
  glClear( GL_COLOR_BUFFER_BIT );

  // TODO: draw our stuff???
//  Gui::DisplayTask(NULL);

  // Render CEGUI.
  CEGUI::System::getSingleton().renderGUI();

  // Update the screen with a page flip.
  SDL_GL_SwapBuffers();
}


void handle_mouse_down(Uint8 button)
{
  switch ( button ) {
    case SDL_BUTTON_LEFT:
      CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::LeftButton);
      break;
    case SDL_BUTTON_MIDDLE:
      CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::MiddleButton);
      break;
    case SDL_BUTTON_RIGHT:
      CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::RightButton);
      break;

    case SDL_BUTTON_WHEELDOWN:
      CEGUI::System::getSingleton().injectMouseWheelChange( -1 );
      break;
    case SDL_BUTTON_WHEELUP:
      CEGUI::System::getSingleton().injectMouseWheelChange( +1 );
      break;
  }
}


void handle_mouse_up(Uint8 button)
{
  switch ( button )
  {
    case SDL_BUTTON_LEFT:
      CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::LeftButton);
      break;
    case SDL_BUTTON_MIDDLE:
      CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::MiddleButton);
      break;
    case SDL_BUTTON_RIGHT:
      CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::RightButton);
      break;
  }
}





} // namespace Gui



